package com.yy.finvideoplayer.media

import android.annotation.TargetApi
import android.content.ContentResolver
import android.content.Context
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.view.Surface
import android.view.SurfaceHolder
import com.yy.finvideoplayer.media.IMediaControl.Companion.MEDIA_ERROR_UNKNOWN

/**
 * @Description: AndroidMedia
 * @Author: yiw89
 * @CreateDate: 2025/9/1 13:41
 * @Version: 1.0
 */
class AndroidMedia(iMediaCallback: IMediaCallback) : BaseMedia(iMediaCallback),
    MediaPlayer.OnPreparedListener,
    MediaPlayer.OnCompletionListener,
    MediaPlayer.OnBufferingUpdateListener,
    MediaPlayer.OnSeekCompleteListener,
    MediaPlayer.OnErrorListener,
    MediaPlayer.OnInfoListener,
    MediaPlayer.OnVideoSizeChangedListener {

    private var mediaPlayer: MediaPlayer? = null

    /////////////以下MediaPlayer控制/////////////
    override fun doPrepare(
        context: Context,
        url: String,
        headers: Map<String, String?>?,
        vararg objects: Any?
    ): Boolean {
        try {
            release()
            mediaPlayer = MediaPlayer()
            mediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC)
            when {
                url.startsWith(ContentResolver.SCHEME_CONTENT) || url.startsWith(ContentResolver.SCHEME_ANDROID_RESOURCE) -> {
                    mediaPlayer?.setDataSource(context, Uri.parse(url), headers)
                }
                url.startsWith(ContentResolver.SCHEME_FILE) -> {
                    mediaPlayer?.setDataSource(url.replace("file:/", ""))
                }
                else -> {
                    try {
                        val clazz = MediaPlayer::class.java
                        val method = clazz.getDeclaredMethod("setDataSource", String::class.java, Map::class.java)
                        method.invoke(mediaPlayer, url, headers) //反射
                    } catch (e: Exception) {
                        e.printStackTrace()
                        mediaPlayer?.setDataSource(url)
                    }
                }
            }
            mediaPlayer?.isLooping = isLooping
            mediaPlayer?.setOnPreparedListener(this)
            mediaPlayer?.setOnCompletionListener(this)
            mediaPlayer?.setOnBufferingUpdateListener(this)
            mediaPlayer?.setScreenOnWhilePlaying(true)
            mediaPlayer?.setOnSeekCompleteListener(this)
            mediaPlayer?.setOnErrorListener(this)
            mediaPlayer?.setOnInfoListener(this)
            mediaPlayer?.setOnVideoSizeChangedListener(this)
            mediaPlayer?.prepareAsync()
            //mediaPlayer?.setDisplay()
            return true
        } catch (e: Exception) {
            e.printStackTrace()
            mediaPlayer?.let { onError(it, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNKNOWN) }
            return false
        }
    }

    @TargetApi(14)
    override fun setSurface(surface: Surface) {
        try {
            mediaPlayer?.setSurface(surface)
            this.surface = surface
        } catch (e: Exception) {
            e.printStackTrace()
            mediaPlayer?.let { onError(it, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNKNOWN) }
        }
    }

    override fun setDisplay(surfaceHolder: SurfaceHolder?) {
        try {
            mediaPlayer?.setDisplay(surfaceHolder)
            this.surface = surfaceHolder?.surface
        } catch (e: Exception) {
            e.printStackTrace()
            mediaPlayer?.let { onError(it, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNKNOWN) }
        }
    }

    override fun doPlay() {
        if (!isPrepar) return
        mediaPlayer?.start()
    }

    override fun doPause() {
        if (!isPrepar) return
        mediaPlayer?.pause()
    }

    override fun seekTo(duration: Int) {
        if (!isPrepar) return
        mediaPlayer?.seekTo(duration)
    }

    override fun getCurrentPosition(): Int {
        if (!isPrepar) return 0
        return try {
            mediaPlayer?.currentPosition ?: 0
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    override fun getDuration(): Int {
        if (!isPrepar) return 0
        return try {
            mediaPlayer?.duration ?: 0
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    override fun getVideoHeight(): Int {
        if (!isPrepar) return 0
        return mediaPlayer?.videoHeight ?: 0
    }

    override fun getVideowidth(): Int {
        if (!isPrepar) return 0
        return mediaPlayer?.videoWidth ?: 0
    }

    override fun isPlaying(): Boolean {
        if (!isPrepar) return false
        return mediaPlayer?.isPlaying ?: false
    }

    override fun setVolume(leftVol: Float, rightVol: Float): Boolean {
        if (leftVol < 0 || rightVol < 0 || leftVol > 1 || rightVol > 1) return false
        if (isPrepar) {
            mediaPlayer?.setVolume(leftVol, rightVol)
        }
        return true
    }

    override fun setSpeed(rate: Float): Boolean {
        if (isPrepar) {
            mediaPlayer?.playbackParams?.let { mediaPlayer?.setPlaybackParams(it.setSpeed(rate)) }
            return true
        }
        return false
    }

    override fun setLooping(isLooping: Boolean) {
        this.isLooping = isLooping
        mediaPlayer?.isLooping = isLooping
    }

    override fun release() {
        isPrepar = false
        this.surface = null
        mediaPlayer?.release()
        mediaPlayer = null
    }

    /////////////以下MediaPlayer回调//////////////
    override fun onPrepared(mp: MediaPlayer) {
        isPrepar = true
        iMediaCallback.onPrepared(this)
    }

    override fun onCompletion(mp: MediaPlayer) {
        iMediaCallback.onCompletion(this)
    }

    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        iMediaCallback.onError(this, what, extra)
        isPrepar = false
        return true
    }

    override fun onBufferingUpdate(mp: MediaPlayer, percent: Int) {
        iMediaCallback.onBufferingUpdate(this, percent / 100.0f)
    }

    override fun onInfo(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        iMediaCallback.onInfo(this, what, extra)
        return false
    }

    override fun onSeekComplete(mp: MediaPlayer) {
        iMediaCallback.onSeekComplete(this)
    }

    override fun onVideoSizeChanged(mp: MediaPlayer, width: Int, height: Int) {
        iMediaCallback.onVideoSizeChanged(this, width, height)
    }
}